namespace SimpleTPL;

using System;
using System.Collections.Generic;
using System.Threading;
using System.Collections.Concurrent;

public static class SimpleThreadPool
{
    private static readonly Lazy<ThreadPoolImpl> _instance = new Lazy<ThreadPoolImpl>(() => new ThreadPoolImpl());
    private static ThreadPoolImpl Instance => _instance.Value;

    public static bool QueueUserWorkItem(WaitCallback callBack, object state = null)
    {
        return Instance.QueueUserWorkItem(callBack, state);
    }

    public static void UnsafeQueueUserWorkItem(WaitCallback callBack, object state = null)
    {
        Instance.QueueUserWorkItem(callBack, state);
    }

    private class ThreadPoolImpl : IDisposable
    {
        private readonly BlockingCollection<(WaitCallback, object)> _workItems = new BlockingCollection<(WaitCallback, object)>();
        private readonly List<Thread> _workerThreads = new List<Thread>();
        private readonly int _maxThreads = Environment.ProcessorCount * 2;
        private bool _isDisposed;

        public ThreadPoolImpl()
        {
            // 创建初始工作线程
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                CreateWorkerThread();
            }
        }

        public bool QueueUserWorkItem(WaitCallback callBack, object state = null)
        {
            if (_isDisposed)
                throw new InvalidOperationException("ThreadPool is disposed");

            if (callBack == null)
                throw new ArgumentNullException(nameof(callBack));

            // 如果没有可用线程且可以创建新线程，则创建新线程
            if (_workerThreads.Count < _maxThreads && _workItems.Count > _workerThreads.Count)
            {
                CreateWorkerThread();
            }

            _workItems.Add((callBack, state));
            return true;
        }

        private void CreateWorkerThread()
        {
            var thread = new Thread(WorkerThreadProc)
            {
                IsBackground = true,
                Name = $"SimpleThreadPool Worker #{_workerThreads.Count + 1}"
            };
            
            lock (_workerThreads)
            {
                _workerThreads.Add(thread);
            }
            thread.Start();
        }

        private void WorkerThreadProc()
        {
            while (!_isDisposed)
            {
                try
                {
                    var (callback, state) = _workItems.Take();
                    try
                    {
                        callback(state);
                    }
                    catch
                    {
                        // 忽略工作项中的异常，与C# ThreadPool行为一致
                    }
                }
                catch (InvalidOperationException)
                {
                    // BlockingCollection 在 disposed 时抛出此异常
                    break;
                }
            }
        }

        public void Dispose()
        {
            if (_isDisposed) return;
            
            _isDisposed = true;
            _workItems.CompleteAdding();
            
            foreach (var thread in _workerThreads)
            {
                thread.Join();
            }
            
            _workItems.Dispose();
        }
    }
}